#pragma once
#ifdef _WIN32
#ifndef ___MOD_MEMORY_HPP
#define ___MOD_MEMORY_HPP
#include "../config.hpp"
#include "detail.hpp"
#include "../binary/binary.hpp"
#include <windows.h>
__MOD_BEGIN
class memory
{
public:
	HANDLE process;
public:
	memory() {}
	memory(HANDLE hProcess) :process(hProcess) {}
	~memory() {}
	template<typename T>
	__memory_detail::read_struct read(T&& Pointer)
	{
		INT_PTR Value = __memory_detail::convert(Pointer);
		__memory_detail::read_struct res(process, Value);
		return res;
	}
	template<typename... Args>
	__memory_detail::read_struct read(Args&&... Pointer)
	{
		std::vector<INT_PTR> list;
		[&] {std::initializer_list<int>{(list.push_back(__memory_detail::convert(Pointer)), 0)...}; }();
		INT_PTR Value = 0;
		size_t Num = list.size();
		if (Num == 1)
		{
		}
		for (size_t i = 0; i < Num; i++)
		{
			ReadProcessMemory(process, (void*)(Value + list[i]), (void*)&Value, sizeof(void*), 0);
		}
		__memory_detail::read_struct res(process, Value);
		return res;
	}
	template<typename T>
	__memory_detail::write_struct write(T&& Pointer)
	{
		INT_PTR Value = __memory_detail::convert(Pointer);
		__memory_detail::write_struct res(process, Value);
		return res;
	}
	template<typename... Args>
	__memory_detail::write_struct write(Args&&... Pointer)
	{
		std::vector<INT_PTR> list;
		[&] {std::initializer_list<int>{(list.push_back(__memory_detail::convert(Pointer)), 0)...}; }();
		INT_PTR Value = 0;
		size_t Num = list.size();
		if (Num == 1)
		{
		}
		for (size_t i = 0; i < Num; i++)
		{
			ReadProcessMemory(process, (void*)(Value + list[i]), (void*)&Value, sizeof(void*), 0);
		}
		__memory_detail::write_struct res(process, Value);
		return res;
	}
	inline DWORD_PTR alloc(SIZE_T size)
	{
		if (size <= 0)
		{
			return 0;
		}
		return (DWORD_PTR)VirtualAllocEx(process, NULL, size, 4096, 64);
	}
	inline DWORD_PTR alloc(LPVOID buff, SIZE_T size)
	{
		DWORD_PTR p = alloc(size);
		if (p <= 65535)
		{
			return 0;
		}
		if (!WriteProcessMemory(process, (LPVOID)p, buff, size, NULL))
		{
			VirtualFreeEx(process, (LPVOID)p, 0, 32768);
			return 0;
		}
		return p;
	}
	inline DWORD_PTR alloc(std::string value)
	{
		SIZE_T size = lstrlenA(value.data()) + 1;
		DWORD_PTR p = alloc(size);
		if (p <= 65535)
		{
			return 0;
		}
		if (!WriteProcessMemory(process, (LPVOID)p, value._Unchecked_begin(), size, NULL))
		{
			VirtualFreeEx(process, (LPVOID)p, 0, 32768);
			return 0;
		}
		return p;
	}
	inline DWORD_PTR alloc(std::wstring value)
	{
		SIZE_T size = lstrlenW(value.data()) * 2 + 2;
		DWORD_PTR p = alloc(size);
		if (p <= 65535)
		{
			return 0;
		}
		if (!WriteProcessMemory(process, (LPVOID)p, value._Unchecked_begin(), size, NULL))
		{
			VirtualFreeEx(process, (LPVOID)p, 0, 32768);
			return 0;
		}
		return p;
	}
	inline DWORD_PTR alloc(mod::binary value)
	{
		SIZE_T size = value.size();
		DWORD_PTR p = alloc(size);
		if (p <= 65535)
		{
			return 0;
		}
		if (!WriteProcessMemory(process, (LPVOID)p, value._Unchecked_begin(), size, NULL))
		{
			VirtualFreeEx(process, (LPVOID)p, 0, 32768);
			return 0;
		}
		return p;
	}
	inline BOOL free(INT_PTR Pointer)
	{
		if (Pointer <= 65535)
		{
			return false;
		}
		return VirtualFreeEx(process, (LPVOID)Pointer, 0, 32768);
	}
private:
};
__MOD_END
#endif
#endif // WIN32